package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.StringUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.bo.LogiCarrierDriverLineQueryBo;
import com.piggy.logi.sys.bo.LogiCarrierExtEditBo;
import com.piggy.logi.sys.bo.LogiCarrierQueryBo;
import com.piggy.logi.sys.domain.LogiCarrier;
import com.piggy.logi.sys.domain.LogiCarrierContract;
import com.piggy.logi.sys.mapper.LogiCarrierMapper;
import com.piggy.logi.sys.service.ILogiCarrierContractService;
import com.piggy.logi.sys.service.ILogiCarrierDriverLineService;
import com.piggy.logi.sys.service.ILogiCarrierService;
import com.piggy.logi.sys.vo.LogiCarrierContractVo;
import com.piggy.logi.sys.vo.LogiCarrierDriverLineExtVo;
import com.piggy.logi.sys.vo.LogiCarrierExtVo;
import com.piggy.logi.sys.vo.LogiCarrierVo;
import com.piggy.sys.api.RemoteDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 承运商信息Service业务层处理
 */
@Slf4j
@Service
public class LogiCarrierServiceImpl extends ServiceImpl<LogiCarrierMapper, LogiCarrier> implements ILogiCarrierService {

    @Resource
    private ILogiCarrierContractService logiCarrierContractService;
    @Resource
    private ILogiCarrierDriverLineService logiCarrierDriverLineService;
    @Resource
    private RemoteDistrictService remoteDistrictService;

    @Override
    public LogiCarrierExtVo queryById(Long id) {
        LogiCarrierExtVo logiCarrierVo = BeanUtil.toBean(getBaseMapper().selectById(id), LogiCarrierExtVo.class);
        if (logiCarrierVo == null) {
            return null;
        }
        List<String> districtIds = Lists.newArrayList(logiCarrierVo.getBusinessDistrictId().toString(), logiCarrierVo.getLocationDistrictId().toString());
        Map<String, String> districtMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();
        logiCarrierVo.setBusinessDistrictName(districtMap.get(logiCarrierVo.getBusinessDistrictId().toString()));
        logiCarrierVo.setLocationDistrictName(districtMap.get(logiCarrierVo.getLocationDistrictId().toString()));

        // 获取合同信息
        List<LogiCarrierContractVo> logiCarrierContractList = logiCarrierContractService.getByCarrierId(logiCarrierVo.getCarrierId());
        logiCarrierVo.setCarrierContractList(logiCarrierContractList);

        // 常跑路线
        LogiCarrierDriverLineQueryBo bo = new LogiCarrierDriverLineQueryBo();
        bo.setCarrierDriverIds(Lists.newArrayList(id));
        bo.setLineType(2);
        List<LogiCarrierDriverLineExtVo> driverLineExtVos = logiCarrierDriverLineService.queryList(bo);
        Map<Long, List<LogiCarrierDriverLineExtVo>> dricerLineMap = driverLineExtVos.stream().collect(Collectors.groupingBy(LogiCarrierDriverLineExtVo::getCarrierDriverId));
        logiCarrierVo.setCarrierLineList(dricerLineMap.get(id));

        return logiCarrierVo;
    }

    @Override
    public TableDataInfo<LogiCarrierExtVo> queryPageList(LogiCarrierQueryBo bo) {
        bo.setDeptId(SecurityUtils.getDeptId());
        PagePlus<LogiCarrier, LogiCarrierExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiCarrierExtVo.class);
        // 填充地址数据
        List<LogiCarrierExtVo> pageListVos = result.getRecordsVo();
        fillData(pageListVos);
        result.setRecordsVo(pageListVos);

        return PageUtils.buildDataInfo(result);
    }

    private void fillData(List<LogiCarrierExtVo> pageListVos) {
        // 填充地址数据
        List<String> districtIds = pageListVos.stream().map(item -> item.getBusinessDistrictId().toString()).distinct().collect(Collectors.toList());
        List<String> localDistrictIds = pageListVos.stream().map(item -> item.getLocationDistrictId().toString()).distinct().collect(Collectors.toList());
        districtIds.addAll(localDistrictIds);
        Map<String, String> districtNameMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();

        // 获取合同信息
        List<Long> carrierIds = pageListVos.stream().map(LogiCarrierVo::getCarrierId).distinct().collect(Collectors.toList());
        List<LogiCarrierContractVo> logiCarrierContractList = logiCarrierContractService.getByCarrierIds(carrierIds);
        Map<Long, List<LogiCarrierContractVo>> carrierContractMap = logiCarrierContractList.stream().collect(Collectors.groupingBy(LogiCarrierContractVo::getCarrierId));

        // 常跑路线
        LogiCarrierDriverLineQueryBo bo = new LogiCarrierDriverLineQueryBo();
        bo.setCarrierDriverIds(carrierIds);
        bo.setLineType(1);
        List<LogiCarrierDriverLineExtVo> driverLineExtVos = logiCarrierDriverLineService.queryList(bo);
        Map<Long, List<LogiCarrierDriverLineExtVo>> dricerLineMap = driverLineExtVos.stream().collect(Collectors.groupingBy(LogiCarrierDriverLineExtVo::getCarrierDriverId));

        pageListVos.forEach(pageListVo -> {
            pageListVo.setBusinessDistrictName(districtNameMap.get(pageListVo.getBusinessDistrictId().toString()));
            pageListVo.setLocationDistrictName(districtNameMap.get(pageListVo.getLocationDistrictId().toString()));
            pageListVo.setCarrierContractList(carrierContractMap.get(pageListVo.getCarrierId()));
            pageListVo.setCarrierLineList(dricerLineMap.get(pageListVo.getCarrierId()));
        });
    }

    @Override
    public List<LogiCarrierExtVo> queryList(LogiCarrierQueryBo bo) {
        bo.setDeptId(SecurityUtils.getDeptId());
        List<LogiCarrierExtVo> extVos = listVo(buildQueryWrapper(bo), LogiCarrierExtVo.class);
        fillData(extVos);
        return extVos;
    }

    private LambdaQueryWrapper<LogiCarrier> buildQueryWrapper(LogiCarrierQueryBo bo) {
        LambdaQueryWrapper<LogiCarrier> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getCarrierName()), LogiCarrier::getCarrierName, bo.getCarrierName());
        lqw.eq(bo.getCarrierType() != null, LogiCarrier::getCarrierType, bo.getCarrierType());
        lqw.eq(bo.getBusinessDistrictId() != null, LogiCarrier::getBusinessDistrictId, bo.getBusinessDistrictId());
        if (StringUtils.isNotBlank(bo.getCreateTimeStr())) {
            lqw.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", bo.getCreateTimeStr());
        }

        lqw.in(CollUtil.isNotEmpty(bo.getIdList()), LogiCarrier::getCarrierId, bo.getIdList());
        // 部门数据权限过滤
        if (ObjectUtil.isNotNull(bo.getDeptId())) {
            SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        }
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(LogiCarrierExtEditBo bo) {
        LogiCarrier add = BeanUtil.toBean(bo, LogiCarrier.class);
        add.setDeptId(SecurityUtils.getDeptId());
        add.setOtherAttachment(JSONUtil.toJsonStr(bo.getOtherAttachment()));
        boolean ret = save(add);

        if (CollUtil.isNotEmpty(bo.getCarrierContractList())) {
            // 添加合同信息
            List<LogiCarrierContract> logiCarrierContractList = Lists.newArrayList();
            bo.getCarrierContractList().forEach(carrierContract -> {
                LogiCarrierContract logiCarrierContract = BeanUtil.toBean(carrierContract, LogiCarrierContract.class);
                logiCarrierContract.setAttachments(JSONUtil.toJsonStr(carrierContract.getAttachments()));
                logiCarrierContractList.add(logiCarrierContract);
            });
            if (CollUtil.isNotEmpty(logiCarrierContractList)) {
                logiCarrierContractList.forEach(logiCarrierContract -> logiCarrierContract.setCarrierId(add.getCarrierId()));
                logiCarrierContractService.saveBatch(logiCarrierContractList);
            }
        }

        if (CollUtil.isNotEmpty(bo.getCarrierLineList())) {
            bo.getCarrierLineList().forEach(item -> {
                item.setLineType(2);
                item.setCarrierDriverId(add.getCarrierId());
            });
            logiCarrierDriverLineService.batchByAddBo(bo.getCarrierLineList());
        }

        return ret;
    }

    @Override
    public Boolean updateByEditBo(LogiCarrierExtEditBo bo) {
        if (bo.getCarrierId() == null) {
            throw new GlobalException("修改ID不能为空");
        }
        LogiCarrier update = BeanUtil.toBean(bo, LogiCarrier.class);
        // 添加合同信息
        if (CollUtil.isNotEmpty(bo.getCarrierContractList())) {
            bo.getCarrierContractList().forEach(contractBo -> {
                contractBo.setCarrierId(bo.getCarrierId());
            });
        }
        logiCarrierContractService.updateContract(bo.getCarrierId(), bo.getCarrierContractList());
        boolean ret = updateById(update);
        if (CollUtil.isNotEmpty(bo.getCarrierLineList())) {
            bo.getCarrierLineList().forEach(item -> {
                item.setLineType(2);
                item.setCarrierDriverId(bo.getCarrierId());
            });
        }
        logiCarrierDriverLineService.batchUpdateByDriverId(bo.getCarrierId(), 2, bo.getCarrierLineList());
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            if (CollUtil.isEmpty(ids)) {
                throw new GlobalException("修改ID不能为空");
            }
        }
        return removeByIds(ids);
    }
}
